package com.gene.tlonpo.service.remote.client;

import com.gene.tlonpo.config.LonpoStaticContext;
import com.gene.tlonpo.service.remote.cache.TlonpoChannelCache;
import com.gene.tlonpo.service.remote.common.model.DataDto;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

/**
 * @author geneX
 * 通信客户端
 */
@Slf4j
public class TlonpoNettyClient {
    public static final TlonpoNettyClient TLONPO_NETTY_CLIENT = new TlonpoNettyClient();

    private TlonpoNettyClient() {
    }

    /**
     * 数据发送
     *
     * @param dataDto 数据
     */
    public void sendData(DataDto dataDto) {
        //寻找缓存
        Channel channel = getChannel(dataDto.getLocalIp(), dataDto.getPort());
        //数据发送
        channel.writeAndFlush(dataDto);
    }

    private Channel getChannel(String host, int port) {
        Channel channel = TlonpoChannelCache.get(host, port);

        if (channel == null) {
            channel = this.connect(host, port);
            TlonpoChannelCache.add(host, port, channel);
        }

        return channel;
    }


    /**
     * 建立新连接
     *
     * @param host host
     * @param port port
     * @return channel
     */
    private Channel connect(String host, Integer port) {
        NioEventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class)
                    .handler(new TlonpoNettyClientChannelInitializer());

            ChannelFuture f = b.connect(host, port).syncUninterruptibly();

            if (f.isSuccess()) {
                log.info("client -> server new connection success");
                return f.channel();
            }

            //通道关闭事件
            f.channel().closeFuture().addListener(future -> log.info("connection is closed"));

        } catch (Exception e) {
            log.error("client -> server new connection fail", e);
            throw new RuntimeException("connec fail");
        }

        return null;
    }


}
